from datetime import datetime
from forward.model.tables.article import ArticleCateGoryModel, ArticleModel
from forward.utils.urls import UrlUtil
from forward.dependencies.database import db
from typing import List

from fastapi_pagination.ext.databases import paginate
from sqlalchemy import insert, select, update

from forward.api.admin.schemas.article import (
    ArticleEditInSchema,
    ArticleChangeInSchema,
    ArticleDeleteInSchema,
    ArticleListInSchema,
    ArticleDetailInSchema,
    ArticleDetailOutSchema,
    ArticleListOutSchema,
    ArticleAddInSchema,
    ArticleSchema,
)


class ArticleService:
    """
    文章分类服务实现类
    """

    async def list_limit(self, limit) -> List[ArticleDetailOutSchema]:
        where = [ArticleModel.is_delete == 0, ArticleModel.is_show == 1]
        article_list_statement = (
            select(ArticleModel)
            .select_from(ArticleModel)
            .outerjoin(
                ArticleCateGoryModel, ArticleModel.cid == ArticleCateGoryModel.id
            )
            .where(*where)
            .order_by(ArticleModel.id.desc())
            .limit(limit)
        )
        article_records = await db.fetch_all(article_list_statement)
        return [
            ArticleDetailOutSchema.model_validate(article_record, from_attributes=True)
            for article_record in article_records
        ]

    async def list(self, list_in: ArticleListInSchema) -> List[ArticleListOutSchema]:
        """
        返回用户收藏的文章ID
        :param list_in:
        :return:
        """
        where = [ArticleModel.is_delete == 0]
        if list_in.title:
            where.append(ArticleModel.title.like("%{0}%".format(list_in.title)))
        if list_in.cid:
            where.append(ArticleModel.cid == list_in.cid)
        if list_in.is_show is not None:
            where.append(ArticleModel.is_show == list_in.is_show)
        if list_in.start_time:
            where.append(ArticleModel.create_time >= list_in.start_time)
        if list_in.end_time:
            where.append(ArticleModel.create_time <= list_in.end_time)

        article_list = (
            select(ArticleModel, ArticleCateGoryModel.name.label("category"))
            .select_from(ArticleModel)
            .outerjoin(
                ArticleCateGoryModel, ArticleModel.cid == ArticleCateGoryModel.id
            )
            .where(*where)
            .order_by(ArticleModel.sort.desc(), ArticleModel.id.desc())
        )
        article_list_pages = await paginate(db, article_list)
        for row in article_list_pages.lists:
            row.image = await UrlUtil.to_absolute_url(row.image)
        return article_list_pages

    async def detail(self, detail_in: ArticleDetailInSchema) -> ArticleDetailOutSchema:
        """
        文章详情
        :return:
        """
        article_detail_record = await db.fetch_one(
            select(ArticleModel)
            .select_from(ArticleModel)
            .where(ArticleModel.id == detail_in.id, ArticleModel.is_delete == 0)
        )
        assert article_detail_record, "文章不存在！"
        article_detail = ArticleDetailOutSchema.model_validate(
            article_detail_record, from_attributes=True
        )
        article_detail.image = await UrlUtil.to_absolute_url(article_detail.image)
        return article_detail

    async def add(self, add_in: ArticleAddInSchema):
        """
        添加文章
        :param add_in:
        :return:
        """
        add_article_dict = add_in.model_dump()

        query = insert(ArticleModel).values(**add_article_dict)
        return await db.execute(query)

    async def edit(self, edit_in: ArticleEditInSchema):
        """
        文章编辑
        :return:
        """

        edit_article = await db.fetch_one(
            select(ArticleModel)
            .select_from(ArticleModel)
            .where(ArticleModel.id == edit_in.id, ArticleModel.is_delete == 0)
        )
        assert edit_article, "文章不存在！"

        edit_article_dict = edit_in.model_dump()
        edit_article_dict["image"] = await UrlUtil.to_relative_url(edit_in.image)

        return await db.execute(
            update(ArticleModel)
            .where(ArticleModel.id == edit_in.id)
            .values(**edit_article_dict)
        )

    async def delete(self, delete_in: ArticleDeleteInSchema):
        """
        文章删除
        :return:
        """
        article_delete = await db.fetch_one(
            select(ArticleModel)
            .select_from(ArticleModel)
            .where(ArticleModel.id == delete_in.id, ArticleModel.is_delete == 0)
        )
        assert article_delete, "文章不存在！"

        return await db.execute(
            update(ArticleModel)
            .where(ArticleModel.id == delete_in.id)
            .values(deleted_time=datetime.now(), is_delete=True)
        )

    async def change(self, change_in: ArticleChangeInSchema):
        """
        文章状态修改
        :param change_in:
        :return:
        """
        article_record = await db.fetch_one(
            select(ArticleModel)
            .select_from(ArticleModel)
            .where(ArticleModel.id == change_in.id, ArticleModel.is_delete == 0)
        )
        assert article_record, "文章不存在！"
        article = ArticleSchema.model_validate(article_record, from_attributes=True)
        new_show_value = not bool(article.is_show)

        return await db.execute(
            update(ArticleModel)
            .where(ArticleModel.id == change_in.id)
            .values(is_show=new_show_value)
        )

    @classmethod
    async def instance(cls):
        """实例化"""
        return cls()
